import javax.imageio.*;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.*;
import java.awt.image.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CustomImageToGif {
    private ImageWriter gifWriter;
    private ImageWriteParam imageWriteParam;
    private IIOMetadata imageMetaData;
    private String outputGifPath;

    public CustomImageToGif(String outputGifPath, int delayMs) throws IOException {
        this.outputGifPath = outputGifPath;

        gifWriter = getWriter();
        imageWriteParam = gifWriter.getDefaultWriteParam();
        ImageTypeSpecifier imageTypeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB);

        imageMetaData = gifWriter.getDefaultImageMetadata(imageTypeSpecifier, imageWriteParam);

        // 设置帧延迟时间
        String metaFormatName = imageMetaData.getNativeMetadataFormatName();
        IIOMetadataNode root = (IIOMetadataNode) imageMetaData.getAsTree(metaFormatName);

        IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension");
        graphicsControlExtensionNode.setAttribute("disposalMethod", "none");
        graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
        graphicsControlExtensionNode.setAttribute("transparentColorFlag", "FALSE");
        graphicsControlExtensionNode.setAttribute("delayTime", Integer.toString(delayMs / 10)); // 帧延迟时间，以1/100秒为单位

        imageMetaData.setFromTree(metaFormatName, root);

        // 创建输出流
        File outputFile = new File(outputGifPath);
        ImageOutputStream ios = ImageIO.createImageOutputStream(outputFile);
        gifWriter.setOutput(ios);

        // 开始写入图像序列
        gifWriter.prepareWriteSequence(null);
    }

    public void writeToGif(BufferedImage image) throws IOException {
        gifWriter.writeToSequence(new IIOImage(image, null, imageMetaData), imageWriteParam);
    }

    public void close() throws IOException {
        gifWriter.endWriteSequence();
    }

    private static ImageWriter getWriter() throws IIOException {
        return ImageIO.getImageWritersBySuffix("gif").next();
    }

    private static IIOMetadataNode getNode(IIOMetadataNode rootNode, String nodeName) {
        int nNodes = rootNode.getLength();
        for (int i = 0; i < nNodes; i++) {
            if (rootNode.item(i).getNodeName().compareToIgnoreCase(nodeName) == 0) {
                return (IIOMetadataNode) rootNode.item(i);
            }
        }
        IIOMetadataNode node = new IIOMetadataNode(nodeName);
        rootNode.appendChild(node);
        return node;
    }

    public static void main(String[] args) throws IOException {
        // 示例用法
        CustomImageToGif customImageToGif = new CustomImageToGif("C:\\Users\\Administrator\\Desktop\\cs\\output.gif", 100); // 指定输出文件路径和帧延迟时间

        BufferedImage customImage = loadImage("C:\\Users\\Administrator\\Desktop\\cs\\咆哮2.jpg"); // 用你的图片替换此处的路径
        // 在循环中添加每一帧
//        for (int i = 0; i < 10; i++) {
//            BufferedImage frame = createFrame(customImage); // 根据你的四叉树分割算法创建帧
//            customImageToGif.writeToGif(frame); // 添加帧到 GIF
//        }

        bufferedImageList=new ArrayList<>();
        bufferedImageList.add(customImage);
        splitImage2(customImage,0.88f);

        System.out.println("frame size= "+bufferedImageList.size() );
        BufferedImage cs=new BufferedImage(customImage.getWidth(),customImage.getHeight(),customImage.getType());
        customImageToGif.writeToGif(cs);
        Collections.reverse(bufferedImageList);
        bufferedImageList.forEach(i->{
            try {
                customImageToGif.writeToGif(i);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        // 关闭 GIF 编写器
        customImageToGif.close();
    }

    // 辅助方法：加载自定义图片
    private static BufferedImage loadImage(String imagePath) throws IOException {
        return ImageIO.read(new File(imagePath));
    }

    // 辅助方法：根据四叉树分割算法创建帧
    private static BufferedImage createFrame(BufferedImage customImage) {
        // 实现你的四叉树分割算法，将customImage分割为不同的图像帧
        // 返回一个BufferedImage对象，表示分割后的图像
        // 示例：返回原始自定义图像
        return customImage;
    }

    static List<BufferedImage> bufferedImageList;

    private static void splitImage(BufferedImage image, int depth) {
        if (depth <= 0) {
            return;
        }

        // 获取图像的宽度和高度
        int width = image.getWidth();
        int height = image.getHeight();

        // 分割图像成四个子图像
        BufferedImage topLeft = image.getSubimage(0, 0, width / 2, height / 2);
//        BufferedImage topRight = image.getSubimage(width / 2, 0, width / 2, height / 2);
//        BufferedImage bottomLeft = image.getSubimage(0, height / 2, width / 2, height / 2);
//        BufferedImage bottomRight = image.getSubimage(width / 2, height / 2, width / 2, height / 2);

        // 分割后保存每个子图像的帧
        System.out.println("saveFrame...");
        bufferedImageList.add(topLeft);
//        bufferedImageList.add(topRight);
//        bufferedImageList.add(bottomLeft);
//        bufferedImageList.add(bottomRight);


        // 递归分割子图像
        splitImage(topLeft, depth - 1);
//        splitImage(topRight, depth - 1);
//        splitImage(bottomLeft, depth - 1);
//        splitImage(bottomRight, depth - 1);
    }


    private static void splitImage2(BufferedImage image, float b) {
        if (image.getWidth() <= 33 || image.getHeight()<33) {
            return;
        }
        BufferedImage cut = image.getSubimage(0, 0, (int) (image.getWidth() *b), (int)(b*image.getHeight()));
        System.out.println("saveFrame...");
        bufferedImageList.add(cut);
        splitImage2(cut,b);
    }
}